package com.shopx.sys.service.impl;


import com.alibaba.fastjson.JSON;
import com.shopx.base.constants.ResultCodeEnum;
import com.shopx.base.exception.OriginException;
import com.shopx.base.exception.ShopxException;
import com.shopx.base.service.ISysSeqService;
import com.shopx.base.service.base.BaseService;
import com.shopx.cmm.DTO.PageDTO;
import com.shopx.core.common.CommonConstant;
import com.shopx.core.utils.DateTimeUtil;
import com.shopx.core.utils.StringUtil;
import com.shopx.sys.bean.SysCompany;
import com.shopx.sys.dao.db1.SysCompanyDao;
import com.shopx.sys.dto.CpTreeDTO;
import com.shopx.sys.dto.CpTreeShowDTO;
import com.shopx.sys.model.SysCompanyModel;
import com.shopx.sys.service.ISysCompanyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @author lituo
 * @className: SysCompany
 * @date 2021-12-07
 */
@Slf4j
@Service
public class SysCompanyServiceImpl extends BaseService implements ISysCompanyService {

    @Resource
    private SysCompanyDao sysCompanyDao;

    @Resource
    private ISysSeqService sysSeqService;

    @Override
    public SysCompanyModel selectByPrimaryKey(SysCompany sysCompany) {
        if (sysCompany == null) {
            throw new ShopxException(ResultCodeEnum.PAR_NULL);
        }
        return sysCompanyDao.selectByPrimaryKey(sysCompany);
    }

    @Override
    public String insertSelective(SysCompany sysCompany) {
        if (sysCompany == null) {
            throw new ShopxException(ResultCodeEnum.PAR_NULL);
        }
        String id = sysSeqService.getTabSeq("SysCompany", 4, null);
        sysCompany.setCpId(id);
        int result = sysCompanyDao.insertSelective(sysCompany);
        if (result != 1) {
            throw new ShopxException(ResultCodeEnum.DB_ERROR);
        }
        return id;
    }

    @Override
    public int updateByPrimaryKeySelective(SysCompany sysCompany) {
        if (sysCompany == null) {
            throw new ShopxException(ResultCodeEnum.PAR_NULL);
        }
        int result = sysCompanyDao.updateByPrimaryKeySelective(sysCompany);
        if (result != 1) {
            throw new ShopxException(ResultCodeEnum.DB_ERROR);
        }
        return result;
    }

    @Override
    public int deleteByPrimaryKey(SysCompany sysCompany) {
        if (sysCompany == null) {
            throw new ShopxException(ResultCodeEnum.PAR_NULL);
        }
        int result = sysCompanyDao.deleteByPrimaryKey(sysCompany);
        if (result != 1) {
            throw new ShopxException(ResultCodeEnum.DB_ERROR);
        }
        return result;
    }

    @Override
    public int selectCount(SysCompanyModel sysCompany) {
        return sysCompanyDao.selectCount(sysCompany);
    }

    @Override
    public List<SysCompanyModel> selectList(SysCompanyModel sysCompany) {
        List<SysCompanyModel> list = sysCompanyDao.selectList(sysCompany);
        return list;
    }

    @Override
    public PageDTO<SysCompanyModel> getListPage(SysCompanyModel sysCompany) {
        if (sysCompany == null) {
            throw new ShopxException(ResultCodeEnum.PAR_NULL);
        }
        PageDTO<SysCompanyModel> pageDTO = new PageDTO<SysCompanyModel>();
        pageDTO.setiTotalDisplayRecords(selectCount(sysCompany));
        pageDTO.setData(selectList(sysCompany));
        return pageDTO;
    }


    @Override
    public PageDTO<SysCompanyModel> queryApplyEnterList(SysCompanyModel sysCompany) {
        if (StringUtil.isEmpty(sysCompany.getCpState())) {
            String[] cpStates = new String[2];
            cpStates[0] = CommonConstant.CpState.INIT;
            cpStates[1] = CommonConstant.CpState.REFUSE;
            sysCompany.setCpStates(cpStates);
        }
        return this.getListPage(sysCompany);
    }

    @Override
    public PageDTO<SysCompanyModel> queryEnterList(SysCompanyModel sysCompany) {
        if (StringUtil.isEmpty(sysCompany.getCpState())) {
            String[] cpStates = new String[2];
            cpStates[0] = CommonConstant.CpState.EFFECTIVE;
            cpStates[1] = CommonConstant.CpState.INVALID;
            sysCompany.setCpStates(cpStates);
        }
        return this.getListPage(sysCompany);
    }


    @Override
    public void checkCompanyState(String cpId) {
        log.info("checkCompanyState.begin:{}", cpId);
        SysCompany param = new SysCompany();
        param.setCpId(cpId);
        SysCompanyModel record = this.selectByPrimaryKey(param);
        if (record == null) {
            throw new OriginException("99999", "绑定企业信息不存在");
        }
        if (!CommonConstant.State.EFFECTIVE.equals(record.getCpState())) {
            log.error("企业已下线:{}", record.getCpState());
            throw new OriginException("99999", "绑定企业信息暂未上线");
        }
//        String cpBegDt = record.getCpBeginDt();
//        String cpEndDt = record.getCpEndDt();
//        String curDt = DateTimeUtil.getDate8();
//        if (cpBegDt.compareTo(curDt) > 0 || cpEndDt.compareTo(curDt) < 0) {
//            log.error("企业不在合同范围.cpBegDt:{},cpEndDt:{}", cpBegDt, cpEndDt);
//            throw new OriginException("99999", "绑定企业信息暂未上线");
//        }
    }


    @Override
    public void giveOrder(SysCompany sysCompany) {
        log.info("giveOrder.begin:{}", sysCompany.getCpId());
        SysCompany sc = new SysCompany();
        sc.setCpId(sysCompany.getCpId());
        sc.setGiveNum(sysCompany.getGiveNum());
        this.updateByPrimaryKeySelective(sc);
    }

    @Override
    public void offline(SysCompany sysCompany) {
        log.info("offline.begin:{}", sysCompany.getCpId());
        SysCompany sc = new SysCompany();
        sc.setCpId(sysCompany.getCpId());
        sc.setCpState(CommonConstant.CpState.INVALID);
        this.updateByPrimaryKeySelective(sc);
    }

    @Override
    public void online(SysCompany sysCompany) {
        log.info("online.begin:{}", sysCompany.getCpId());
        SysCompany sc = new SysCompany();
        sc.setCpId(sysCompany.getCpId());
        sc.setCpState(CommonConstant.CpState.EFFECTIVE);
        this.updateByPrimaryKeySelective(sc);
    }

    @Override
    public SysCompanyModel entDetail() {
        String cpId = super.getUserCpId();
        SysCompany sysCompany = new SysCompany();
        sysCompany.setCpId(cpId);
        return this.selectByPrimaryKey(sysCompany);
    }

    @Override
    public void entUpdate(SysCompany sysCompany) {
        String cpId = super.getUserCpId();
        sysCompany.setCpId(cpId);
        this.updateByPrimaryKeySelective(sysCompany);
    }

    @Override
    public BigDecimal queryCompanyBalance(String cpId) {
        Long balance = sysCompanyDao.selectCompanyBalance(cpId);
        return new BigDecimal(balance);
    }

    @Override
    public SysCompany companySignOrder(String cpId, String projId) {
        log.info("reduceBalance.projId:{}，cpId:{}", projId, cpId);
        SysCompany sysCompany = new SysCompany();
        sysCompany.setCpId(cpId);
        SysCompanyModel model = sysCompanyDao.selectByPrimaryKey(sysCompany);
        if (model == null) {
            throw new OriginException("企业信息不存在");
        }
        BigDecimal billMoney = new BigDecimal(0);
        BigDecimal giveNum = model.getGiveNum();
        if (giveNum.compareTo(new BigDecimal(0)) > 0) {
            log.info("赠送订单:{}", giveNum);
            giveNum = giveNum.subtract(new BigDecimal(1));
            //修改赠送工地
            sysCompany.setGiveNum(giveNum);
            this.updateByPrimaryKeySelective(sysCompany);
            sysCompany.setBillType("9");
            sysCompany.setBillAmount(billMoney);
            sysCompany.setCpMoney(model.getCpMoney());
            return sysCompany;
        }

        sysCompany.setBillType(model.getBillType());
        if (!cpId.equals(super.getUserCpId())) {
            throw new ShopxException(ResultCodeEnum.BUSI_NO_AUTH_DATA_ACCESS);
        }
        if (!CommonConstant.CpState.EFFECTIVE.equals(model.getCpState())) {
            throw new OriginException("企业资料尚未审核通过，请联系管理员！");
        }

        String billType = model.getBillType();
        log.info("billType:{}", billType);
        if (CommonConstant.BillType.NUM.equals(billType) || CommonConstant.BillType.RATIO.equals(billType)) {
            billMoney = this.reduceCompanyBalance(model);
            sysCompany.setBillAmount(billMoney);
            sysCompany.setCpMoney(model.getCpMoney().subtract(billMoney));
            return sysCompany;
        } else if (CommonConstant.BillType.MTH.equals(billType) || CommonConstant.BillType.YEAR.equals(billType)) {
            String begDt = model.getBillBeginDt();
            String endDt = model.getBillEndDt();
            String curDt = DateTimeUtil.getDate8();
            if (curDt.compareTo(endDt) > 0 || curDt.compareTo(begDt) < 0) {
                throw new OriginException("企业包月/年合同到期或者未开始，请联系管理员！");
            }
            sysCompany.setBillAmount(billMoney);
            sysCompany.setCpMoney(model.getCpMoney());
            return sysCompany;
        } else {
            throw new OriginException("企业计费类型错误，请联系管理员！");
        }
    }

    /**
     * @param model
     * @return void
     * @descript 按单扣费
     * @author lituo
     * @date 2022/3/1 14:34
     */
    private BigDecimal reduceCompanyBalance(SysCompanyModel model) {
        BigDecimal billAmount = new BigDecimal(0);
        BigDecimal cpMoney = model.getCpMoney();
        SysCompany sc = new SysCompany();
        sc.setCpId(model.getCpId());
        if (CommonConstant.BillType.NUM.equals(model.getBillType())) {
            //单笔收费
            billAmount = model.getBillAmount();
        } else if (CommonConstant.BillType.RATIO.equals(model.getBillType())) {
            //比例收费
            billAmount = model.getProjSPrice().multiply(model.getBillAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        if (billAmount.compareTo(cpMoney) >= 0) {
            throw new OriginException("企业余额不足，无法签单。请联系管理员充值");
        }
        sc.setBillAmount(model.getBillAmount());
        int result = sysCompanyDao.updateCompanyBalance(sc);
        if (result != 1) {
            throw new ShopxException(ResultCodeEnum.DB_ERROR);
        }
        return billAmount;
    }

    @Override
    public List<CpTreeShowDTO> selectCpTree(SysCompany sc) {
        //获取当前用户所有公司
        String cpIds = "";
        if(StringUtil.isEmpty(sc.getCpId())){
            cpIds = super.getUserCpId();
        }else{
            cpIds = sc.getCpId();
        }
        if(StringUtil.isEmpty(cpIds)){
            throw new OriginException("请绑定企业查询");
        }

        //获取所有的公司列表
        SysCompany sysCompany = new SysCompany();
        sysCompany.setCpState("1");
        List<CpTreeDTO> cpList = sysCompanyDao.selectCpTree();

        //获取上级菜单
        List<CpTreeDTO> treeList = new ArrayList<>();
        //转成map
        Map<String, CpTreeDTO> cpMap = cpList.stream().collect(Collectors.toMap(cp -> cp.getCpId(), cp -> cp));
        //最终
        List<CpTreeDTO> resultList = new ArrayList<>();

        //获取登录用户所在的分公司
        for (String cpId : cpIds.split(",")) {
            treeList.add(cpMap.get(cpId));
        }
        //获取分公司的所有上级公司节点
        for (String cpId : cpIds.split(",")) {
            CpTreeDTO curCp = cpMap.get(cpId);
            while (curCp != null && !StringUtil.isEmpty(curCp.getParCpId())) {
                curCp = cpMap.get(curCp.getParCpId());
                if (curCp == null) {
                    continue;
                }
                treeList.add(curCp);
            }
        }
        //去重
        resultList = treeList.stream()
                .collect(Collectors.toMap(CpTreeDTO::getCpId, bean -> bean, (oldValue, newValue) -> oldValue))
                .values()
                .stream()
                .collect(Collectors.toList());

        //转换成树结构
        List<CpTreeShowDTO> tree = convertToTree(resultList);
        return tree;
    }


    private List<CpTreeShowDTO> convertToTree(List<CpTreeDTO> list) {
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }
        // 将 List 转换为 Map，方便根据 parCpId 查找子节点
        Map<String, List<CpTreeDTO>> map = new HashMap<>();
        for (CpTreeDTO dto : list) {
            if(dto.getParCpId() == null || dto.getParCpId().isEmpty()){
                dto.setParCpId("0");
            }
            if (!map.containsKey(dto.getParCpId())) {
                map.put(dto.getParCpId(), new ArrayList<>());
            }
            map.get(dto.getParCpId()).add(dto);
        }

        // 查找根节点（parCpId 为 null 或为空的节点）
        List<CpTreeDTO> rootNodes = map.get("0");

        List<CpTreeShowDTO> result = new ArrayList<>();
        if (rootNodes != null) {
            for (CpTreeDTO rootNode : rootNodes) {
                CpTreeShowDTO treeNode = new CpTreeShowDTO();
                treeNode.setId(rootNode.getCpId());
                treeNode.setTitle(rootNode.getCpName());
                treeNode.setLevel(rootNode.getCpLevel());
                treeNode.setChildren(buildChildren(rootNode.getCpId(), map));
                result.add(treeNode);
            }
        }
        return result;
    }

    private static List<CpTreeShowDTO> buildChildren(String parentId, Map<String, List<CpTreeDTO>> map) {
        List<CpTreeDTO> childrenNodes = map.get(parentId);
        if (childrenNodes == null || childrenNodes.isEmpty()) {
            return null;
        }

        List<CpTreeShowDTO> children = new ArrayList<>();
        for (CpTreeDTO childNode : childrenNodes) {
            CpTreeShowDTO treeNode = new CpTreeShowDTO();
            treeNode.setId(childNode.getCpId());
            treeNode.setTitle(childNode.getCpName());
            treeNode.setLevel(childNode.getCpLevel());
            List<CpTreeShowDTO> grandChildren = buildChildren(childNode.getCpId(), map);
            treeNode.setChildren(grandChildren);
            children.add(treeNode);
        }
        return children;
    }

}

